package chapter19;

import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.SessionCallback;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.Pipeline;
import utils.ContextUtils;

import java.util.List;

/**
 * Redis的流水线
 */
public class Demo2 {

    public static void main(String[] args) {
//        pipelineBySpring();
        pipelinedByJedis();
    }

    public static void incorret(){
        RedisTemplate redisTemplate = (RedisTemplate) new ClassPathXmlApplicationContext("spring-redis.xml").getBean("redisTemplate");
        SessionCallback sessionCallback = new SessionCallback() {
            @Override
            public Object execute(RedisOperations redisOperations) throws DataAccessException {
                for (int i=0;i < 1000000 ;i++) {
                    int j = i+1;
                    redisOperations.boundValueOps("pipeline_key_" + j).set( "pipeline_value_" + j);
                    redisOperations.boundValueOps("pipeline_key_" + j).get();
                }
                return null;
            }
        };
        Long start =  System.currentTimeMillis();
        List results = redisTemplate.executePipelined(sessionCallback);
        Long end= System.currentTimeMillis();
        System.err.println("耗时：" + (end - start) + "毫秒");
    }

    /**
     * 371毫秒   3927毫秒
     */
    public static void pipelineBySpring(){
        RedisTemplate redisTemplate = (RedisTemplate) new ClassPathXmlApplicationContext("spring-redis.xml").getBean("redisTemplate");
        SessionCallback sessionCallback = (SessionCallback) (RedisOperations operations) -> {
            for (int i=0;i < 1000000 ;i++) {
                int j = i+1;
                operations.boundValueOps("pipeline_key_" + j).set( "pipeline_value_" + j);
                operations.boundValueOps("pipeline_key_" + j).get();
            }
            return null;
        };
        Long start =  System.currentTimeMillis();
        List results = redisTemplate.executePipelined(sessionCallback);
        Long end= System.currentTimeMillis();
        System.err.println("耗时：" + (end - start) + "毫秒");
    }

    /**
     * 323毫秒,操作底层的Jedis直接进行命令执行 2838毫秒
     */
    public static void pipelinedByJedis(){
        RedisTemplate redisTemplate = ContextUtils.getBean("redisTemplate");
        Jedis jedis = (Jedis) redisTemplate.getConnectionFactory().getConnection().getNativeConnection();
        long start = System.currentTimeMillis();
        // 开启流水线
        Pipeline pipeline = jedis.pipelined();
        // 这里测试10万条的读写2个操作
        for (int i=0;i < 1000000 ;i++) {
            int j = i+1;
            pipeline.set("pipeline_key_" + j, "pipeline_value_" + j);
            pipeline.get("pipeline_key_" + j);
        }
        // pipelien.sync();  这里只执行同步，不会返回List列表结果
        // pipeline.syncAndReturnAll() 将返回执行过的命令返回的List列表结果
        List results = pipeline.syncAndReturnAll();
        Long end = System.currentTimeMillis();
        System.err.println("耗时：" + (end - start) + "毫秒");
    }


/**
 * 总结：
 *  使用底层的Jedis操作流水线要比使用spring操作流水线要快
 *  如果使用10万条数据进行一个读写两个操作，使用Jedis进行要比使用spring执行要快50毫秒
 *  如果使用100万条数据进行一个读写两个操作，使用Jedis进行要比使用Spring执行要快1000多毫秒
 *  性能上操作数据越多，差别越大
 */

}
